package com.example.testelc.controller;

import com.example.testelc.domain.ResultVO;
import com.example.testelc.domain.User;
import com.example.testelc.repostrory.EsService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

@RestController
public class EsController {
    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;
    @Autowired
    private EsService esUserService;

    private String[] names={"诸葛亮","曹操","李白","韩信","赵云","小乔","狄仁杰","李四","诸小明","王五"};
    private String[] infos={"我来自中国的一个小乡村，地处湖南省","我来自中国的一个大城市，名叫上海，人们称作魔都"
            ,"我来自东北，家住大囤里，一口大碴子话"};

    @GetMapping("saveUser")
    public ResultVO saveUser(){
    	//添加索引mapping    索引会自动创建但mapping自只用默认的这会导致分词器不生效 所以这里我们手动导入mapping
        elasticsearchTemplate.putMapping(User.class);
        Random random = new Random();
        List<User> users = new ArrayList<>();
        for (int i=0;i<20;i++){
            User user = new User();
            user.setId(i);
            user.setName(names[random.nextInt(9)]);
            user.setAge(random.nextInt(40)+i);
            user.setInfo(infos[random.nextInt(2)]);
            users.add(user);
        }
        Iterable<User> users1 = esUserService.saveAll(users);
        return new ResultVO(users1);
    }


    @GetMapping("getDataById")
    public ResultVO getDataById(Integer id){
        return new ResultVO(esUserService.findById(id));
    }


    @GetMapping("getAllDataByPage")
    public ResultVO getAllDataByPage(){
        //本该传入page和size，这里为了方便就直接写死了
        Pageable page = PageRequest.of(0,10, Sort.Direction.ASC,"id");
        Page<User> all = esUserService.findAll(page);
        return new ResultVO(all.getContent());
    }


    @GetMapping("getDataByName")
    public ResultVO getDataByName(String name){
        return new ResultVO(esUserService.findByName(name));
    }


    @GetMapping("getDataByNameAndInfo")
    public ResultVO getDataByNameAndInfo(String name,String info){
        //这里是查询两个字段取交集，即代表两个条件需要同时满足
        return new ResultVO(esUserService.findByNameAndInfo(name,info));
    }
    

    @GetMapping("getHightByUser")
    public ResultVO getHightByUser(String value){
        //根据一个值查询多个字段  并高亮显示  这里的查询是取并集，即多个字段只需要有一个字段满足即可
        //需要查询的字段
        BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery()
                .should(QueryBuilders.matchQuery("info",value))
                .should(QueryBuilders.matchQuery("name",value));
        Pageable of = PageRequest.of(0, 3);
        //构建高亮查询
        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(boolQueryBuilder).withPageable(of)
                .withHighlightFields(
                        new HighlightBuilder.Field("info")
                        ,new HighlightBuilder.Field("name"))
                .withHighlightBuilder(new HighlightBuilder().preTags("<span style='color:red'>").postTags("</span>"))
                .build();
       
        //查询
        SearchHits<User> search = elasticsearchTemplate.search(searchQuery, User.class);
        //得到查询返回的内容
        List<SearchHit<User>> searchHits = search.getSearchHits();
        //设置一个最后需要返回的实体类集合
        List<User> users = new ArrayList<>();
        //遍历返回的内容进行处理
        for(SearchHit<User> searchHit:searchHits){
            //高亮的内容
            Map<String, List<String>> highlightFields = searchHit.getHighlightFields();
            //将高亮的内容填充到content中
            searchHit.getContent().setName(highlightFields.get("name")==null ? searchHit.getContent().getName():highlightFields.get("name").get(0));
            searchHit.getContent().setInfo(highlightFields.get("info")==null ? searchHit.getContent().getInfo():highlightFields.get("info").get(0));
            //放到实体类中
            users.add(searchHit.getContent());
        }
        return new ResultVO(users);
    }

}
